<?php

namespace Tug\Controller;

use Plume\Core\Controller;
use Plume\Core\Service;
use Plume\Core\Dao;
use Tug\Utils\InputUtils;

class RuntimeController extends Controller
{
    private $redis;
    private $gameSetService;
    private $teamsService;
    public function __construct($app) {
        parent::__construct($app);
        $this->gameSetService = new Service($app, new Dao($app, 'game_set'));
        $this->teamsService = new Service($app, new Dao($app, 'teams'));
        $this->redis = new \Redis();
        $redisInfo = $this->getConfigValue('redis');
        if (!$this->redis->connect($redisInfo['host'], $redisInfo['port'])) {
            file_put_contents('redis_error.txt', date('Y-m-d H:i:s').'redis连接错误！'.PHP_EOL, 8);
        }
    }
    public function headCountAction()
    {
        // 游戏准备状态，大屏轮询调用。显示红队和蓝队有多少人加入游戏
        try {
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $this->redis->get($roundKey);
            $joinRedKey =  "user_red:{$sequence}_{$round}";
            $joinBlueKey =  "user_blue:{$sequence}_{$round}";
            $red = $this->redis->zCard($joinRedKey);
            $blue = $this->redis->zCard($joinBlueKey);
            $bkDt = ['lNum' => $red, 'rNum' => $blue];
        } catch (\Exception $e) {
            $bkDt = ['errCode' => -100, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function waitAction()
    {
        try {
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $gameInfoKey = "game_set:{$meetId}_{$sequence}";
            $redTeamInfoKey = "teams:{$sequence}_1";
            $blueTeamInfoKey = "teams:{$sequence}_2";
            $gameInfo = $this->redis->hGetAll($gameInfoKey);
            $redTeamInfo = $this->redis->hGetAll($redTeamInfoKey);
            $blueTeamInfo = $this->redis->hGetAll($blueTeamInfoKey);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $gameInfo['round'] = $this->redis->get($roundKey);
            if (empty($gameInfo)) {
                $where = ['sequence' => $sequence];
                $redWhere = ['sequence' => $sequence, 'type' => 1];
                $blueWhere = ['sequence' => $sequence, 'type' => 2];
                $gameInfo = $this->gameSetService->fetch($where);
                $redTeamInfo = $this->teamsService->fetch($redWhere);
                $blueTeamInfo = $this->teamsService->fetch($blueWhere);
                if (!empty($gameInfo)) {
                    $bkData = array(
                        'gameInfo' => $gameInfo[0], 'redInfo' =>$redTeamInfo[0],
                        'blueInfo' => $blueTeamInfo[0] ,'reCode' => 1,'end' => 999, 'mf' => 1
                    );
                } else {
                    $bkData = array('reCode' => 0, 'msg' => '不存在的拔河，请到环节设置中设置。');
                }
            } else {
                $bkData = array(
                    'gameInfo' => $gameInfo, 'redInfo' =>$redTeamInfo,
                    'blueInfo' => $blueTeamInfo ,'reCode' => 1,'end' => 999, 'mf' => 1
                );
            }
        } catch (\Exception $e) {
            $bkData = ['code' => -1, 'msg' => $e->getMessage()];
        }
        echo json_encode($bkData);exit;
    }
    // ready mean change game status
    public function gameStartAction()
    {
         try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $this->redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            $gameInfoKey = "game_set:{$meetId}_{$sequence}";
            $limit = (int)$redis->hGet($gameInfoKey, 'limit');
            if ($gameStatus == 1) { // game exists && is not begin
                $startTime = time();
                $data = ['startTime' => $startTime, 'status' => 2, 'overTime' => $limit + $startTime];
                $bool = $redis->hMset($gameStatusInfoKey, $data);
                if ($bool) {
                    $bkDt = ['recode'=> 1 , 'msg' => '游戏成功开始'];
                } else {
                    $bkDt = ['recode'=> 0 , 'msg' => '开始游戏失败'];
                }
            } else {
                $bkDt = ['recode'=> -1 , 'msg' => '游戏进行中或已结束！'];
            }
        } catch (\Exception $e) {
             $bkDt =['recode' => -300, 'status' => 0, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function initialAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'status'];
            list($meetId, $sequence, $status) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $this->redis->get($roundKey);
            $joinRedKey =  "user_red:{$sequence}_{$round}";
            $joinBlueKey =  "user_blue:{$sequence}_{$round}";
            $joinRed = $redis->zCard($joinRedKey);
            $joinBlue = $redis->zCard($joinBlueKey);
            if($joinBlue + $joinRed < 2) { // 如果人数不为零并且 红蓝人数相同
                $bkDt = ['res' => -3, 'msg' => '人数不足'];
            } else {
                if ($joinRed > $joinBlue) {
                    $redis->zRemRangeByRank($joinRedKey,$joinBlue, -1);
                    $bkDt = ['res' => 1, 'msg' => '裁剪红队人数成功，游戏可以开始'];
                } else if ($joinRed < $joinBlue){
                    $redis->zRemRangeByRank($joinRedKey,$joinRed, -1);
                    $bkDt = ['res' => 1, 'msg' => '裁剪蓝队人数成功，游戏可以开始'];
                } else {
                    $bkDt = ['res' => 1, 'msg' => '红队==蓝队'];
                }
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit (json_encode($bkDt));
    }
    public function gameAgainAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'endTime');
            if ($gameStatus['endTime'] < time()){
                $bkDt =['recode' => -1,  'msg' => '上一轮游戏还没结束！'];
            } else {
                $roundKey = "game_round:{$meetId}_{$sequence}";    // 再来一次
                $round = $redis->get($roundKey);
                $round++;
                $redis->multi();
                $bool = $redis->set($roundKey, $round);
                $gameStatusInfo = [
                    'sequence' => $sequence, 'status' => 1, 'win' => 0,
                    'blue_score' => '0', 'red_score' => 0, 'round' => $round
                ];
                $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
                $bool2 = $redis->hMset($gameStatusInfoKey, $gameStatusInfo);
                if ($bool && $bool2) {
                    $redis->exec();
                    $bkDt = ['recode' => 1, 'msg' => '可以再来一次'];
                } else {
                    $redis->discard();
                    $bkDt = ['recode' => -1, 'msg' => '再来一次数据初始化失败'];
                }
            }
        }catch (\Exception $e) {
            $bkDt = ['recode' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function tuggingAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            $redPower = 0; $bluePower = 0;
            if($gameStatus !== false){
                $joinRedKey =  "user_red:{$sequence}_{$round}";
                $joinBlueKey =  "user_blue:{$sequence}_{$round}";
                $redUserOpenid = $redis->zRange($joinRedKey, 0, -1);
                $blueUserOpenId = $redis->zRange($joinBlueKey, 0, -1);
                foreach($redUserOpenid as $openid) {
                    $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                    $redPower  += (int)$redis->hGet($userGameResultKey, 'total');
                }
                foreach($blueUserOpenId as $openid) {
                    $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                    $bluePower  += (int)$redis->hGet($userGameResultKey, 'total');
                }
                $bkDt = ['res' => 1, 'left' => $redPower, 'right' => $bluePower];
            } else {
                $bkDt = ['res' => -100, 'msg' => '不存在的游戏！'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function startAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'round'];
            list($meetId, $sequence, $round) = InputUtils::issetOrFail('post', $must);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_{$round}";
            $gameStatus = $redis->hGet($gameStatusInfoKey,'status');
            if($gameStatus !== false) {
                $joinRedKey =  "user_red:{$sequence}_{$round}";
                $joinBlueKey =  "user_blue:{$sequence}_{$round}";
                $redUserOpenid = $this->redis->zRange($joinRedKey, 0, 10);
                $blueUserOpenId = $this->redis->zRange($joinBlueKey, 0, 10);
                $redUserInfo = [];
                foreach ($redUserOpenid as  $openid){
                    $userInfoKey = "user:{$openid}";
                    $redUserInfo[] = $redis->hGetAll($userInfoKey);
                }
                $blueUserInfo = [];
                foreach ($blueUserOpenId as  $openid){
                    $userInfoKey = "user:{$openid}";
                    $blueUserInfo[] = $redis->hGetAll($userInfoKey);
                }
                $players = $redis->zCard($joinRedKey); // 有多少人玩游戏 red*2
                $bkDt = [
                    'res' => 1, 'msg' => '获取成功！！', 'players' => $players,
                    'l_u' => $redUserInfo, 'r_u' => $blueUserInfo
                ];
            } else {
                $bkDt = ['res' => -100, 'msg' => '游戏数据不存在'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt, true));
    }
    public function overAction()
    {
        try{
            $redis = $this->redis;
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            if($gameStatus == 2 || $gameStatus == 3) {
                $redPower = 0; $bluePower = 0;
                $joinRedKey =  "user_red:{$sequence}_{$round}";
                $joinBlueKey =  "user_blue:{$sequence}_{$round}";
                $redUserOpenid = $redis->zRange($joinRedKey, 0, -1);
                $blueUserOpenId = $redis->zRange($joinBlueKey, 0, -1);
                foreach($redUserOpenid as $openid) {
                    $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                    $redPower  += (int)$redis->hGet($userGameResultKey, 'total');
                }
                foreach($blueUserOpenId as $openid) {
                    $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                    $bluePower  += (int)$redis->hGet($userGameResultKey, 'total');
                }
                if ($redPower == $bluePower) {
                    $win = 0;
                } else if ($redPower > $bluePower){
                    $win = 1;
                } else {
                    $win = 2;
                }
                $set = ['status' => 3, 'blue_score' => $bluePower, 'red_score' => $redPower, 'win' => $win];
                $bool = $redis->hMset($gameStatusInfoKey, $set);
                if ($bool) {
                    $bkDt = ['res' => 1, 'msg' => '游戏结束成功!'];
                } else {
                    $bkDt = ['res' => -1, 'msg' => '游戏结束失败!'];
                }
            } else {
              $bkDt = ['res' => -3, 'msg' => '游戏状态不允许改变!'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function statisticAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence'];
            list($meetId, $sequence) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $redis->get($roundKey); // 游戏进行到第几轮
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            if ($gameStatus == 3) {
                $redTeamInfoKey = "teams:{$sequence}_1";
                $blueTeamInfoKey = "teams:{$sequence}_2";
                $redTeamInfo = $this->redis->hGetAll($redTeamInfoKey);
                $blueTeamInfo = $this->redis->hGetAll($blueTeamInfoKey);
                $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_{$round}";
                $gameStatusInfo = $redis->hGetAll($gameStatusInfoKey);
                $winTeamUsers = [];
                if ($gameStatusInfo['win'] == 1) {
                    $joinRedKey =  "user_red:{$sequence}_{$round}";
                    $redUserOpenid = $redis->zRange($joinRedKey, 0, -1);
                    foreach($redUserOpenid as $openid) {
                        $userInfoKey = "user:{$openid}";
                        $winTeamUsers[] = $redis->hMGet($userInfoKey, ['nickname', 'headimgurl']);
                    }
                } else {
                    $joinBlueKey =  "user_blue:{$sequence}_{$round}";
                    $blueUserOpenId = $redis->zRange($joinBlueKey, 0, -1);
                    foreach($blueUserOpenId as $openid) {
                        $userInfoKey = "user:{$openid}";
                        $winTeamUsers[] = $redis->hMGet($userInfoKey, ['nickname', 'headimgurl']);
                    }
                }
                $bkDt = [
                    'res' => 1, 'gameStatusInfo' => $gameStatusInfo,
                    'redTeamInfo' => $redTeamInfo, 'blueTeamInfo' => $blueTeamInfo,
                    'winTeamUsers' => $winTeamUsers
                ];
            } else {
                $bkDt = ['res' => '-100', 'msg' => '游戏不存在 || 游戏正在进行中 '];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function resultAction()
    {
        $server_url = $this->getConfigValue("server_url");
        return array('server_url' => $server_url);
    }
    public function __destruct()
    {
        $this->redis->close();
    }
}